﻿using System;
using System.Collections.Generic;
using DI = Microsoft.DirectX.DirectInput;
using Microsoft.Xna.Framework.Input;
namespace DXJoystickSupport
{
    public class DXJoyState
    {
        private bool isConected = false;
        private readonly DXJoyButtons buttons = new DXJoyButtons();
        private object lockState;

        public DXJoyButtons Buttons
        {
            get { return buttons; }
        }

        public DXJoyState()
        {
            lockState = new object();
        }

        internal void Update(DI.Device joystick)
        {
            lock (lockState)
            {
                DI.JoystickState joystickState = joystick.CurrentJoystickState;
                DI.DeviceCaps deviceCaps = joystick.Caps;
                isConected = deviceCaps.Attatched;

                #region buttons
                DXJoyButton[] todosBotoes = new DXJoyButton[] {
                                                        DXJoyButton.Button01,
                                                        DXJoyButton.Button02,
                                                        DXJoyButton.Button03,
                                                        DXJoyButton.Button04,
                                                        DXJoyButton.Button05,
                                                        DXJoyButton.Button06,
                                                        DXJoyButton.Button07,
                                                        DXJoyButton.Button08,
                                                        DXJoyButton.Button09,
                                                        DXJoyButton.Button10,
                                                        DXJoyButton.Button11,
                                                        DXJoyButton.Button12
                                                    };
                byte[] buttonArray = joystickState.GetButtons();//retorna 128 posicoes, independente do numero de botoes existente
                ButtonState state;

                for (int i = 0; i < todosBotoes.Length; i++)
                {
                    if (buttonArray[i] == 0)
                        state = ButtonState.Released;
                    else
                        state = ButtonState.Pressed;
                    buttons.Update(todosBotoes[i], state);
                }
                #endregion

                #region axis
                string[] todosEixos = new string[4] { "X", "Y", "Z", "rZ" };
                Dictionary<string, DXJoyButton[]> todosBotoesEixo = new Dictionary<string, DXJoyButton[]>(4);
                todosBotoesEixo.Add("X", new DXJoyButton[] { DXJoyButton.NegativeXAxis, DXJoyButton.PositiveXAxis });
                todosBotoesEixo.Add("Y", new DXJoyButton[] { DXJoyButton.NegativeYAxis, DXJoyButton.PositiveYAxis });
                todosBotoesEixo.Add("Z", new DXJoyButton[] { DXJoyButton.NegativeZAxis, DXJoyButton.PositiveZAxis });
                todosBotoesEixo.Add("rZ", new DXJoyButton[] { DXJoyButton.NegativerZAxis, DXJoyButton.PositiverZAxis });

                int valorEixo = 0;
                const int valorMaxEixo = 65535;
                for (int j = 0; j < todosEixos.Length; j++)
                {
                    if (todosEixos[j].Equals("X"))
                    {
                        valorEixo = joystickState.X;
                    }
                    else if (todosEixos[j].Equals("Y"))
                    {
                        valorEixo = joystickState.Y;
                    }
                    else if (todosEixos[j].Equals("Z"))
                    {
                        valorEixo = joystickState.Z;
                    }
                    else if (todosEixos[j].Equals("rZ"))
                    {
                        valorEixo = joystickState.Rz;
                    }
                    if (valorEixo.CompareTo((int)(valorMaxEixo * 0.4999925f)) < 0)
                    {
                        buttons.Update(todosBotoesEixo[todosEixos[j]][0], ButtonState.Pressed);
                        buttons.Update(todosBotoesEixo[todosEixos[j]][1], ButtonState.Released);
                    }
                    else if (valorEixo.CompareTo((int)(valorMaxEixo * 0.5000077f)) > 0)
                    {
                        buttons.Update(todosBotoesEixo[todosEixos[j]][0], ButtonState.Released);
                        buttons.Update(todosBotoesEixo[todosEixos[j]][1], ButtonState.Pressed);
                    }
                    else
                    {
                        buttons.Update(todosBotoesEixo[todosEixos[j]][0], ButtonState.Released);
                        buttons.Update(todosBotoesEixo[todosEixos[j]][1], ButtonState.Released);
                    }
                }
                #endregion

                #region pointOfView

                Dictionary<int, DXJoyButton> todosBotoesPOV = new Dictionary<int, DXJoyButton>(8);
                todosBotoesPOV.Add(0, DXJoyButton.PointOfViewN);
                todosBotoesPOV.Add(45, DXJoyButton.PointOfViewNE);
                todosBotoesPOV.Add(90, DXJoyButton.PointOfViewE);
                todosBotoesPOV.Add(135, DXJoyButton.PointOfViewSE);
                todosBotoesPOV.Add(180, DXJoyButton.PointOfViewS);
                todosBotoesPOV.Add(225, DXJoyButton.PointOfViewSW);
                todosBotoesPOV.Add(270, DXJoyButton.PointOfViewW);
                todosBotoesPOV.Add(315, DXJoyButton.PointOfViewNW);

                int povangle = joystickState.GetPointOfView()[0];

                for (int k = 0; k < 360; k += 45)
                {
                    if (povangle.Equals(k * 100))
                    {
                        buttons.Update(todosBotoesPOV[k], ButtonState.Pressed);
                    }
                    else
                    {
                        buttons.Update(todosBotoesPOV[k], ButtonState.Released);
                    }
                }

                #endregion
            }
        
        }

        public bool IsConected
        {
            get { return isConected; }
        }

        public bool IsButtonDown(DXJoyButton button)
        {
            lock (lockState)
            {
                return buttons.State(button).Equals(ButtonState.Pressed);
            }
        }

        public bool IsButtonUp(DXJoyButton button)
        {
            lock (lockState)
            {
                return buttons.State(button).Equals(ButtonState.Released);
            }
        }
    }
}
